package com.example.shuiyin;

import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.availability.AvailabilityChangeEvent;
import org.springframework.boot.availability.LivenessState;
import org.springframework.boot.availability.ReadinessState;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.event.EventListener;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.validation.annotation.Validated;

import javax.sql.DataSource;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Arrays;

@SpringBootApplication
@Slf4j
@MapperScan("com.example.shuiyin.mapper")
@EnableScheduling
@ConfigurationPropertiesScan("com.example.shuiyin.config")
@Validated
public class ShuiyinApplication {

	private static boolean emergencyMode = false;

	static {
		// 设置系统属性，跳过Flyway迁移
		System.setProperty("skipFlyway", "true");
	}

	public static void main(String[] args) {
		try {
			log.info("=== 水印应用启动中 ===");
			log.info("JDK版本: {}", System.getProperty("java.version"));
			log.info("操作系统: {}", System.getProperty("os.name"));
			
			// 检查MySQL服务是否运行
			boolean mysqlRunning = isMysqlRunning("localhost", 3306);
			if (!mysqlRunning) {
				log.error("MySQL服务未运行，进入应急模式 - 部分功能将不可用");
				System.out.println("警告: MySQL服务未运行，应用将以有限功能模式启动");
				emergencyMode = true;
			}
			
			// 输出启动参数
			log.info("启动参数: {}", Arrays.toString(args));
			
			// 设置应急模式系统属性
			if (emergencyMode) {
				System.setProperty("shuiyin.emergency-mode", "true");
			}
			
			// 设置使用prod环境配置
			System.setProperty("spring.profiles.active", "prod");
			log.info("已设置使用生产环境配置(prod)");
			
			// 确保允许循环引用
			System.setProperty("spring.main.allow-circular-references", "true");
			log.info("已设置允许循环引用");
			
			// 启动Spring应用
			SpringApplication app = new SpringApplication(ShuiyinApplication.class);
			ConfigurableApplicationContext ctx = app.run(args);
			log.info("应用上下文创建成功，Bean总数: {}", ctx.getBeanDefinitionCount());
			
			// 如果是应急模式，注册关闭钩子
			if (emergencyMode) {
				Runtime.getRuntime().addShutdownHook(new Thread(() -> {
					log.info("应用关闭中 (应急模式)...");
				}));
			}
		} catch (Exception e) {
			log.error("应用启动过程中发生严重错误: {}", e.getMessage(), e);
			System.err.println("严重错误: 应用启动失败 - " + e.getMessage());
			System.exit(1);
		}
	}
	
	/**
	 * 检查MySQL服务是否运行
	 */
	private static boolean isMysqlRunning(String host, int port) {
		log.info("检查MySQL服务状态 {}:{}...", host, port);
		try (Socket socket = new Socket()) {
			socket.connect(new InetSocketAddress(host, port), 1000);
			log.info("MySQL服务检测：运行中 ({}:{})", host, port);
			return true;
		} catch (Exception e) {
			log.error("MySQL服务检测：未运行 ({}:{}) - {}", host, port, e.getMessage());
			return false;
		}
	}
	
	/**
	 * 监控应用可用性事件
	 */
	@EventListener
	public void onAvailabilityChange(AvailabilityChangeEvent<?> event) {
		if (event.getState() instanceof LivenessState) {
			log.info("应用存活状态变更为: {}", event.getState());
		} else if (event.getState() instanceof ReadinessState) {
			log.info("应用就绪状态变更为: {}", event.getState());
		}
	}
	
	@Bean
	public CommandLineRunner checkConfiguration(DataSource dataSource) {
		return args -> {
			log.info("应用配置检查开始");
			log.info("应用紧急模式: {}", emergencyMode ? "已启用" : "未启用");
			log.info("激活的配置环境: {}", System.getProperty("spring.profiles.active", "default"));
			log.info("数据源类型: {}", dataSource.getClass().getName());
			
			try (Connection connection = dataSource.getConnection()) {
				log.info("数据库连接成功: {}", connection.getMetaData().getURL());
				// 测试数据库版本
				log.info("数据库版本: {}", connection.getMetaData().getDatabaseProductVersion());
				// 测试是否可以执行简单查询
				try (var stmt = connection.createStatement()) {
					try (var rs = stmt.executeQuery("SELECT 1")) {
						if (rs.next()) {
							log.info("数据库测试查询成功：{}", rs.getInt(1));
						}
					}
				}
				log.info("数据库连接测试完成：正常");
			} catch (SQLException e) {
				log.error("数据库连接失败: {}", e.getMessage(), e);
				if (!emergencyMode) {
					emergencyMode = true;
					System.setProperty("shuiyin.emergency-mode", "true");
					log.warn("系统已切换至应急模式，部分功能将不可用");
				}
			}
			
			log.info("应用配置检查完成");
		};
	}
	
	@Bean
	public ApplicationRunner diagnosticRunner() {
		return args -> {
			log.info("======= 应用诊断信息 =======");
			log.info("Java版本: {}", System.getProperty("java.version"));
			log.info("操作系统: {}", System.getProperty("os.name"));
			log.info("工作目录: {}", System.getProperty("user.dir"));
			log.info("激活的配置环境: {}", System.getProperty("spring.profiles.active", "default"));
			log.info("应急模式: {}", System.getProperty("shuiyin.emergency-mode", "false"));
			log.info("可用处理器数: {}", Runtime.getRuntime().availableProcessors());
			log.info("最大内存: {}MB", Runtime.getRuntime().maxMemory() / (1024 * 1024));
			log.info("总内存: {}MB", Runtime.getRuntime().totalMemory() / (1024 * 1024));
			log.info("空闲内存: {}MB", Runtime.getRuntime().freeMemory() / (1024 * 1024));
			log.info("============================");
			
			if (emergencyMode) {
				log.warn("应用处于应急模式，功能可能受限，请检查数据库连接和配置");
			} else {
				log.info("应用正常运行中");
			}
		};
	}
}
